package com.cosmosource.core.config.datasource;

import com.alibaba.druid.pool.DruidDataSource;
import com.cosmosource.core.properties.DataSourceProperties;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.mapping.DatabaseIdProvider;
import org.apache.ibatis.mapping.VendorDatabaseIdProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.CollectionUtils;

import javax.sql.DataSource;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;


/**
 * @author wyc
 * @date 2022/5/7
 */
@Slf4j
@Configuration
public class DataSourceConfiguration {

    @Autowired
    private DataSourceProperties dataSourceProperties;

    @Value("${cosmosource.datasource.external-jdbcdriver-path:../com/public/customPackage}")
    private String jdbcPackage;

    @Bean
    public DataSource dataSource() throws Exception {
        URLClassLoader urlClassLoader = new URLClassLoader(this.getJdbcJarUrl(jdbcPackage));
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassLoader(urlClassLoader);
        dataSource.setUrl(dataSourceProperties.getUrl());
        dataSource.setDriverClassName(dataSourceProperties.getDriverClassName());
        dataSource.setUsername(dataSourceProperties.getUsername());
        dataSource.setPassword(dataSourceProperties.getPassword());
        dataSource.setValidationQuery(dataSourceProperties.getPool().getValidationQuery());
        dataSource.setTestWhileIdle(dataSourceProperties.getPool().isTestWhileIdle());
        dataSource.setDefaultAutoCommit(true);
        //判断非空，并对dataSource属性赋值
        dataSource.setFilters(dataSourceProperties.getPool().getFilters());
        dataSource.setMaxActive(Integer.parseInt(dataSourceProperties.getPool().getMaxActive()));
        dataSource.setMinIdle(Integer.parseInt(dataSourceProperties.getPool().getMinIdle()));
        dataSource.setMaxActive(Integer.parseInt(dataSourceProperties.getPool().getMaxActive()));
        dataSource.setMaxWait(Integer.parseInt(dataSourceProperties.getPool().getMaxWait()));
        dataSource.setTimeBetweenConnectErrorMillis(Integer.parseInt(dataSourceProperties.getPool().getTimeBetweenEvictionRunsMillis()));
        dataSource.setTestOnBorrow(Boolean.parseBoolean(dataSourceProperties.getPool().getTestOnBorrow()));
        dataSource.setTestOnReturn(Boolean.parseBoolean(dataSourceProperties.getPool().getTestOnReturn()));
        dataSource.setPoolPreparedStatements(Boolean.parseBoolean(dataSourceProperties.getPool().getPoolPreparedStatements()));
        dataSource.setMaxOpenPreparedStatements(Integer.parseInt(dataSourceProperties.getPool().getMaxOpenPreparedStatements()));
        dataSource.setAsyncInit(Boolean.parseBoolean(dataSourceProperties.getPool().getAsyncInit()));
        return dataSource;
    }

    @Bean
    public DatabaseIdProvider getDatabaseIdProvider() {
        DatabaseIdProvider databaseIdProvider = new VendorDatabaseIdProvider();
        Properties properties = new Properties();
        properties.setProperty("MySQL", "mysql");
        properties.setProperty("KingbaseES", "kingbase");
        properties.setProperty("PostgreSQL", "gaussdws");
        databaseIdProvider.setProperties(properties);
        return databaseIdProvider;
    }


    /**
     * 获取各个厂商jdbc驱动jar包的URL
     *
     * @param jdbcPackage jdbc驱动包路径
     * @return URL集合
     */
    private URL[] getJdbcJarUrl(String jdbcPackage) throws Exception {
        File file = new File(jdbcPackage);
        // 判断包下是否有驱动jar包，不存在则抛错，存在则遍历获取所有驱动URL
        if (!file.exists() || !file.isDirectory()) {
            log.error("JDBC驱动路径错误：{}", jdbcPackage);
            throw new Exception("无法加载JDBC驱动路径：" + jdbcPackage);
        }

        File[] filePacks = file.listFiles();
        if (filePacks == null) {
            log.error("当前组件下没有驱动（not jdbc path）");
            throw new Exception(jdbcPackage + "下没有jdbc驱动信息");
        }

        // 返回结果
        List<URL[]> list = getResultList(filePacks);
        if (CollectionUtils.isEmpty(list)) {
            log.error("当前组件下没有相关的配置驱动（not jdbc config）");
            throw new Exception(jdbcPackage + "下没有相对应的jdbc配置驱动信息");
        }
        return list.get(0);
    }

    /**
     * 获取配置的驱动
     *
     * @param filePacks
     * @throws MalformedURLException
     */
    private List<URL[]> getResultList(File[] filePacks) throws MalformedURLException {
        List<URL[]> list = new ArrayList<>();
        for (File pack : filePacks) {
            if (!pack.isDirectory()) {
                continue;
            }
            if (StringUtils.isNotBlank(dataSourceProperties.getType())
                    && StringUtils.isNotBlank(dataSourceProperties.getVersion())
                    && pack.getName().equals(dataSourceProperties.getType())) {
                pack = new File(pack.toURI().getPath() + "/" + dataSourceProperties.getVersion());
            } else {
                continue;
            }
            File[] files = pack.listFiles();
            if (files != null && files.length > 0) {
                // 需要加载的jdbc包
                URL[] urls = new URL[files.length];
                for (int i = 0; i < files.length; i++) {
                    urls[i] = (files[i].toURI().toURL());
                }
                list.add(urls);
            }
        }
        return list;
    }
}
